package com.motong.gongdan.controller.system;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.motong.gongdan.config.CustomCellWriteHandler;
import com.motong.gongdan.config.ResponseData;
import com.motong.gongdan.config.auth.UserLoginToken;
import com.motong.gongdan.entity.BomInfo;
import com.motong.gongdan.entity.Product;
import com.motong.gongdan.entity.User;
import com.motong.gongdan.service.BomInfoService;
import com.motong.gongdan.service.ProductService;
import com.motong.gongdan.service.UserService;
import com.motong.gongdan.util.LoginUtil;
import com.motong.gongdan.util.RedisUtil;
import com.motong.gongdan.vo.ExcelModel.BMOExcelModel;
import com.motong.gongdan.vo.system.AssemblyWorkOrder.query.ListByProductIdQuery;
import com.motong.gongdan.vo.system.AssemblyWorkOrder.vo.AssemblyDetailProductVo;
import com.motong.gongdan.vo.system.BOM.query.BOMListQuery;
import com.motong.gongdan.vo.system.BOM.query.ListGroupByProductQuery;
import com.motong.gongdan.vo.system.BOM.vo.BOMListVo;
import com.motong.gongdan.vo.system.common.query.IdValueQuery;
import com.motong.gongdan.vo.system.otherVo.ExcelImportLog;
import com.motong.gongdan.vo.system.otherVo.IdVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Api(tags = "物料清单")
@RestController
@RequestMapping("/sys/BOM")
public class BOMInfoController {

    @Resource
    private BomInfoService bomInfoService;

    @Resource
    private ProductService productService;

    @Resource
    private UserService userService;

    @ApiOperation("获取物料清单列表")
    @PostMapping("/getList")
    @UserLoginToken
    public ResponseData<List<BOMListVo>> getList(@RequestBody(required = false) BOMListQuery query) {
        query = Optional.ofNullable(query).orElse(new BOMListQuery());
        Page<BOMListVo> data = bomInfoService.getList(new Page<>(query.getPage(), query.getLimit()), query);
        return ResponseData.success(data.getRecords(), data.getTotal());
    }

    @ApiOperation("获取物料清单详情(传id)")
    @PostMapping("/getDetail")
    @UserLoginToken
    public ResponseData<BomInfo> getDetail(@RequestBody IdVo query) {
        if (Objects.nonNull(query.getId())) {
            BomInfo bomInfo = bomInfoService.getById(query.getId());
            return ResponseData.success(bomInfo);
        }
        return ResponseData.success(null);
    }

    @ApiOperation("编辑物料清单")
    @PostMapping("/edit")
    @UserLoginToken
    @Transactional(rollbackFor = Exception.class)
    public ResponseData<String> edit(@RequestBody BomInfo bomInfo) {
        boolean isUpdate = Objects.nonNull(bomInfo.getId());
        Integer userId = LoginUtil.getLoginUserId();
        LambdaQueryWrapper<BomInfo> repeatQW = new LambdaQueryWrapper<BomInfo>().ne(isUpdate, BomInfo::getId, bomInfo.getId())
                .eq(BomInfo::getParentProductId, bomInfo.getParentProductId()).eq(BomInfo::getChildProductId, bomInfo.getChildProductId());
        if (bomInfoService.count(repeatQW) > 0) {
            return ResponseData.fail("系统已存在相同物料清单");
        }
        if (isUpdate) {
            bomInfo.setUpdateUser(userId).setUpdateTime(new Date());
        } else {
            bomInfo.setCreateUser(userId).setCreateTime(new Date());
        }
        bomInfoService.saveOrUpdate(bomInfo);
        return ResponseData.success(isUpdate ? "编辑成功!" : "添加成功!");
    }

    @ApiOperation("删除物料清单信息")
    @PostMapping("/del")
    @UserLoginToken
    public ResponseData<String> del(@RequestBody IdValueQuery query) {
        if (!CollectionUtils.isEmpty(query.getIdList())) {
            bomInfoService.removeByIds(query.getIdList());
        }
        return ResponseData.success("删除成功!");
    }

    @ApiOperation("获取物料清单及子集")
    @PostMapping("/getListByProductId")
    @UserLoginToken
    public ResponseData<List<AssemblyDetailProductVo>> getListByProductId(@RequestBody ListByProductIdQuery query) {
        List<AssemblyDetailProductVo> data = bomInfoService.getListByProductId(query.getProductIdList(), query.getGetChild());
        return ResponseData.success(data);
    }

    @ApiOperation("获取物料清单列表(按产品分组)")
    @PostMapping("/getListGroupByProduct")
    @UserLoginToken
    public ResponseData<List<Product>> getListGroupByProduct(@RequestBody(required = false) ListGroupByProductQuery query) {
        query = Optional.ofNullable(query).orElse(new ListGroupByProductQuery());
        Page<Product> data = bomInfoService.getListGroupByProduct(new Page<>(query.getPage(), query.getLimit()), query);
        return ResponseData.success(data.getRecords(), data.getTotal());
    }

    @UserLoginToken
    @PostMapping("/BOMImport")
    @ApiOperation(value = "导入物料清单")
    public ResponseData<String> BOMImport(MultipartFile file, Integer type) throws IOException {
        ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
        List<Map> mapData = reader.read(1, 2, Map.class);
        Integer userId = LoginUtil.getLoginUserId();
        User user = userService.getById(userId);
        Map<String, Integer> dataMap = new HashMap<>(2);
        if (!CollectionUtils.isEmpty(mapData)) {
            List<BomInfo> bomInfos = new ArrayList<>();
            List<ExcelImportLog> excelImportLogs = new ArrayList<>();
            mapData.forEach(i -> {
                String parentProductCode = Convert.toStr(i.get("父项产品编号"));
                String parentProductName = Convert.toStr(i.get("父项产品名称"));
                String parentProductSpecification = Convert.toStr(i.get("父项产品规格"));
                String childProductCode = Convert.toStr(i.get("子项产品编号"));
                String childProductName = Convert.toStr(i.get("子项产品名称"));
                String childProductSpecification = Convert.toStr(i.get("子项产品规格"));
                BomInfo bomInfo = new BomInfo().setUnitUsage(Convert.toBigDecimal(i.get("单位用量"))).setRemark(Convert.toStr(i.get("备注")));
                Product parentProduct = null;
                if (StringUtils.hasLength(parentProductCode)) {
                    parentProduct = productService.getOne(new LambdaQueryWrapper<Product>().eq(Product::getCode, parentProductCode));
                } else if (StringUtils.hasLength(parentProductName) && StringUtils.hasLength(parentProductSpecification)) {
                    parentProduct = productService.getOne(new LambdaQueryWrapper<Product>()
                            .eq(Product::getName, parentProductName).eq(Product::getSpecification, parentProductSpecification));
                }
                Product childProduct = null;
                if (StringUtils.hasLength(childProductCode)) {
                    childProduct = productService.getOne(new LambdaQueryWrapper<Product>().eq(Product::getCode, childProductCode));
                } else if (StringUtils.hasLength(childProductName) && StringUtils.hasLength(childProductSpecification)) {
                    childProduct = productService.getOne(new LambdaQueryWrapper<Product>()
                            .eq(Product::getName, childProductName).eq(Product::getSpecification, childProductSpecification));
                }
                if (Objects.nonNull(parentProduct) && Objects.nonNull(childProduct)) {
                    bomInfo.setParentProductId(parentProduct.getId()).setChildProductId(childProduct.getId());
                    if (type == 0) {
                        bomInfo.setCreateUser(userId).setCreateTime(new Date());
                    } else if (type == 1) {
                        BomInfo oriBomInfo = bomInfoService.getOne(new LambdaQueryWrapper<BomInfo>().eq(BomInfo::getParentProductId, bomInfo.getParentProductId())
                                .eq(BomInfo::getChildProductId, bomInfo.getChildProductId()));
                        if (Objects.nonNull(oriBomInfo)) {
                            bomInfo.setId(oriBomInfo.getId()).setUpdateUser(userId).setUpdateTime(new Date());
                            bomInfos.add(bomInfo);
                        } else {
                            i.put("失败原因", "物料清单不存在");
                            excelImportLogs.add(new ExcelImportLog().setAccount(user.getAccount()).setCreateTime(new Date())
                                    .setReason(Collections.singletonList(i)));
                        }

                    }
                    BomInfo oriBomInfo = bomInfoService.getOne(new LambdaQueryWrapper<BomInfo>().eq(BomInfo::getParentProductId, bomInfo.getParentProductId())
                            .eq(BomInfo::getChildProductId, bomInfo.getChildProductId()).ne(type == 1, BomInfo::getId, bomInfo.getId()));
                    if (Objects.nonNull(oriBomInfo)) {
                        i.put("失败原因", "系统已存在相同物料清单");
                        excelImportLogs.add(new ExcelImportLog().setAccount(user.getAccount()).setCreateTime(new Date())
                                .setReason(Collections.singletonList(i)));
                    }
                    bomInfos.add(bomInfo);
                } else {
                    i.put("失败原因", "产品不存在");
                    excelImportLogs.add(new ExcelImportLog().setAccount(user.getAccount()).setCreateTime(new Date())
                            .setReason(Collections.singletonList(i)));
                }
            });
            if (!CollectionUtils.isEmpty(excelImportLogs)) {
                dataMap.put("updateSuccess", 0);
                dataMap.put("updateFail", 0);
                dataMap.put("createSuccess", 0);
                dataMap.put("createFail", 0);
                if (type == 0) {
                    dataMap.put("createSuccess", 0);
                    dataMap.put("createFail", mapData.size());
                } else {
                    dataMap.put("updateSuccess", 0);
                    dataMap.put("updateFail", mapData.size());
                }

                JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(excelImportLogs.get(0).setData(dataMap).setCount(mapData.size())));
                JSONArray jsonArray = (JSONArray) RedisUtil.get("excel:import:" + "BOM" + ":" + LoginUtil.getLoginUserFactory());
                if (jsonArray == null) {
                    jsonArray = new JSONArray();
                }
                jsonArray.add(jsonObject);
                RedisUtil.set("excel:import:" + "BOM" + ":" + LoginUtil.getLoginUserFactory(), jsonArray, 259200);
            }
            if (!CollectionUtils.isEmpty(bomInfos) && CollectionUtils.isEmpty(excelImportLogs)) {
                bomInfoService.saveOrUpdateBatch(bomInfos);
                dataMap.put("updateSuccess", 0);
                dataMap.put("updateFail", 0);
                dataMap.put("createSuccess", 0);
                dataMap.put("createFail", 0);
                if (type == 0) {
                    dataMap.put("createSuccess", bomInfos.size());
                    dataMap.put("createFail", mapData.size() - bomInfos.size());
                } else {
                    dataMap.put("updateSuccess", bomInfos.size());
                    dataMap.put("updateFail", mapData.size() - bomInfos.size());
                }
                ExcelImportLog excelImportLog = new ExcelImportLog().setAccount(user.getAccount()).setCount(mapData.size()).setCreateTime(new Date())
                        .setData(dataMap);
                JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(excelImportLog));
                JSONArray jsonArray = (JSONArray) RedisUtil.get("excel:import:" + "BOM" + ":" + LoginUtil.getLoginUserFactory());
                if (jsonArray == null) {
                    jsonArray = new JSONArray();
                }
                jsonArray.add(jsonObject);
                RedisUtil.set("excel:import:" + "BOM" + ":" + LoginUtil.getLoginUserFactory(), jsonArray, 259200);
            }
        } else {
            dataMap.put("createSuccess", 0);
            dataMap.put("createFail", 0);
            dataMap.put("updateSuccess", 0);
            dataMap.put("updateFail", 0);
            ExcelImportLog excelImportLog = new ExcelImportLog().setAccount(user.getAccount()).setCount(0).setCreateTime(new Date()).setData(null);
            JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(excelImportLog));
            JSONArray jsonArray = (JSONArray) RedisUtil.get("excel:import:" + "BOM" + ":" + LoginUtil.getLoginUserFactory());
            if (jsonArray == null) {
                jsonArray = new JSONArray();
            }
            jsonArray.add(jsonObject);
            RedisUtil.set("excel:import:" + "BOM" + ":" + LoginUtil.getLoginUserFactory(), jsonArray, 259200);
        }
        return ResponseData.success("导入成功!");
    }

    @UserLoginToken
    @PostMapping("/export")
    @ApiOperation(value = "导出物料清单")
    public void outSProductMergerRefundsExcel(@RequestBody(required = false) BOMListQuery query, HttpServletResponse response) {
        List<BOMListVo> data = this.getList(query).getData();
        if (!CollectionUtils.isEmpty(data)) {
            try {
                Stream.iterate(0, i -> (i + 1)).limit(data.size()).forEach(i -> data.get(i).setId((long) (i + 1)));
                List<BMOExcelModel> exportData = data.stream().map(i -> {
                    BMOExcelModel bmoExcelModel = new BMOExcelModel();
                    BeanUtil.copyProperties(i, bmoExcelModel);
                    bmoExcelModel.setCreateTime(new DateTime(i.getCreateTime()).toString());
                    if (Objects.nonNull(i.getUpdateTime())) {
                        bmoExcelModel.setUpdateTime(new DateTime(i.getUpdateTime()).toString());
                    }
                    return bmoExcelModel;
                }).collect(Collectors.toList());

                String fileName = "物料清单" + System.currentTimeMillis() + ".xlsx";
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
                EasyExcel.write(response.getOutputStream()).registerWriteHandler(new CustomCellWriteHandler()).sheet("物料清单导出数据").head(BMOExcelModel.class).doWrite(exportData);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
